package fiuba.algo3.modelo;

import java.io.IOException;

import fiuba.algo3.modelo.mapa.Mapa;
import fiuba.algo3.modelo.vehiculo.TipoDeVehiculo;
import fiuba.algo3.modelo.vehiculo.Vehiculo;
import fiuba.algo3.persistencia.Restaurador;

public class Partida {

	private Mapa mapa;
	private Vehiculo vehiculo;
	private Posicion meta;
	private int cantidadMaximaDeMovimientos;
	private Dificultad dificultad;
	

	public Partida(Dificultad dificultad, Mapa mapa, Vehiculo vehiculo, Posicion posicionMeta, int cantidadMaximaDeMovimientos){
		this.dificultad = dificultad;
		this.mapa = mapa;
		this.cantidadMaximaDeMovimientos = cantidadMaximaDeMovimientos;
		this.meta = posicionMeta;
		this.vehiculo = vehiculo;
	}

	public static Partida nuevaPartidaConPosicionesAleatorias(Dificultad dificultad, TipoDeVehiculo tipoDeVehiculo) throws IOException {
		int cantidadMaximaDeMovimientos = 60;
		Mapa mapa = (Mapa) Restaurador.levantarDe("mapa"+dificultad.toString()+".xml");
		Posicion posicionMeta = Posicion.crearPosicionAleatoria(mapa.getAncho(), mapa.getAlto());

		// Para asegurarse que la meta y el vehiculo no arrancan en la misma posicion:
		Posicion posicionInicialVehiculo = Posicion.crearPosicionAleatoria(mapa.getAncho(), mapa.getAlto());
		boolean vehiculoYMetaEstanEnElMismoLugar = 	posicionMeta.equals(posicionInicialVehiculo);
		while (vehiculoYMetaEstanEnElMismoLugar){
			posicionInicialVehiculo = Posicion.crearPosicionAleatoria(mapa.getAncho(), mapa.getAlto());
			vehiculoYMetaEstanEnElMismoLugar = 	posicionMeta.equals(posicionInicialVehiculo);
		}
		
		Vehiculo vehiculo = new Vehiculo(tipoDeVehiculo, posicionInicialVehiculo, mapa);	
		Partida partida = new Partida(dificultad, mapa, vehiculo, posicionMeta, cantidadMaximaDeMovimientos); 
		return partida;
	}
	
	public Estado moverVehiculoHacia(Direccion direccion){
		vehiculo.moverA(direccion);
		return getEstado();
	}
	
	public Estado getEstado(){
		int movimientosHechos = vehiculo.getMovimientos();
		boolean llegoALaMeta = (vehiculo.getCruceActual() == mapa.getCruceEn(meta));

		if (movimientosHechos > cantidadMaximaDeMovimientos) return Estado.PERDIDA;
		if (movimientosHechos == cantidadMaximaDeMovimientos && !llegoALaMeta) return Estado.PERDIDA;
	
		if (llegoALaMeta) return Estado.GANADA;
		
		return Estado.EN_CURSO;
	}

	public Mapa getMapa(){
		return mapa;
	}
	
	//usado solo en tests
	public int getCantidadMaximaDeMovimientos(){
		return cantidadMaximaDeMovimientos;
	}
	
	public int getCantidadDeMovimientosRestantes(){
		return cantidadMaximaDeMovimientos - vehiculo.getMovimientos();
	}
	
	public Posicion getPosicionDeLaMeta(){
		return meta;
	}
	
	public Vehiculo getVehiculo(){
		return vehiculo;
	}
	
	public int getPuntaje(){
		return dificultad.bonus()*getCantidadDeMovimientosRestantes();
	}
}
